package com.cx.base.day19_thread;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

/**
 * @Author: robert.song
 * @Date: Created in 2021/8/10
 */
@Slf4j(topic = "Thread_7_保护性暂停模式扩展")
public class Thread_7_保护性暂停模式扩展 {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            new People().start();
        }
        Thread.sleep(1);

        for (Integer id : Mailboxes.getIds()) {
            new Postman(id, "内容" + id).start();
        }
    }
}

@Slf4j(topic = "people")
class People extends Thread {
    public void run() {
//        收信
        GuardedObject2 guardedObject2 = Mailboxes.createGuardedObject2();
        log.info("开始收信 id：{}", guardedObject2.getId());
        Object mail = guardedObject2.get(5000);
        log.info("收到信件 id:{},内容:{}", guardedObject2.getId(), mail);
    }
}

@Slf4j(topic = "postman")
class Postman extends Thread {
    private int id;
    private String mail;

    public Postman(int id, String mail) {
        this.id = id;
        this.mail = mail;
    }

    @Override
    public void run() {
        GuardedObject2 guardedObject2 = Mailboxes.getGuardedObject2(id);
        log.info("送信件 id:{},内容 {}", id, mail);
        guardedObject2.complete(mail);
    }
}

@Data
class Mailboxes {
    private static Map<Integer, GuardedObject2> boxes = new Hashtable<>();
    private static int id = 1;

    //    产生唯一id
    private static synchronized int generateId() {
        return id++;
    }

    public static GuardedObject2 getGuardedObject2(int id) {
        return boxes.remove(id);
    }

    public static GuardedObject2 createGuardedObject2() {
        GuardedObject2 go = new GuardedObject2(generateId());
        boxes.put(go.getId(), go);
        return go;
    }

    public static Set<Integer> getIds() {
        return boxes.keySet();
    }
}

//增加超时效果
class GuardedObject2 {
    //    标识 Guarded Object
    private int id;

    public GuardedObject2(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    //    结果
    private Object response;

    //    获取结果
//    timeout表示等待时间
    public Object get(long timeout) {
        synchronized (this) {
            long begin = System.currentTimeMillis();
            //            没有结果
            long passedTime = 0;
            while (response == null) {
                //                这一轮循环应该等待的时间
                long waitTime = timeout - passedTime;
                if (waitTime <= 0) {
                    break;
                }
                try {
                    this.wait(waitTime);
                    passedTime = System.currentTimeMillis();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return response;
        }
    }

    //    产生结果
    public void complete(Object response) {
        synchronized (this) {
//            给姐u共成员变量赋值
            this.response = response;
            this.notifyAll();
        }
    }
}